home *** CD-ROM | disk | FTP | other *** search
/ Aminet 43 / Aminet 43 (2001)(GTI - Schatztruhe)[!][Jun 2001].iso / Aminet / comm / tcp / Amster-source.lha / Amster_Install / Source / share.c < prev    next >
C/C++ Source or Header  |  2001-03-27  |  32KB  |  1,196 lines

  1. /*
  2. ** Amster - File Sharing
  3. ** Copyright © 2000-2001 by Jacob Laursen
  4. **
  5. ** This program is free software; you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation; either version 2 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program; if not, write to the Free Software
  17. ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18. */
  19.  
  20. #include "amster.h"
  21.  
  22. #include <MUI/NListview_mcc.h>
  23.  
  24. #include <proto/asl.h>
  25. #include <proto/dos.h>
  26. #include <libraries/asl.h>
  27. #include <libraries/dos.h>
  28. #include <exec/memory.h>
  29. #include <dos/exall.h>
  30. #include <utility/tagitem.h>
  31. #include <workbench/workbench.h>
  32.  
  33. #include "md5.h"
  34. #include "amster_Cat.h"
  35.  
  36.  
  37. unsigned int numsongs=0, numbytes=0;
  38. BOOL sharechanged=FALSE, sharefailed=FALSE;
  39.  
  40. struct FileRequester *FReqAddFiles;
  41. struct FileRequester *FReqAddDir;
  42. struct FileRequester *FReqLibrary;
  43.  
  44.  
  45. MUI_DISPATCH(share_dispatch)
  46. {
  47.     struct shdata *data;
  48.  
  49.     switch(msg->MethodID) {
  50.         case OM_NEW:
  51.             return(share_new(cl, obj, (APTR)msg));
  52.         case OM_DISPOSE:
  53.             if (FReqAddFiles) FreeAslRequest(FReqAddFiles);
  54.             if (FReqAddDir)   FreeAslRequest(FReqAddDir);
  55.             if (FReqLibrary)  FreeAslRequest(FReqLibrary);
  56.             break;
  57.         case SHARE_OPEN:
  58.             data = INST_DATA(cl, obj);
  59.             update_stat(data);
  60.             set(obj, MUIA_Window_Open, TRUE);
  61.             return NULL;
  62.         case SHARE_CLOSE:
  63.             set(obj, MUIA_Window_Open, FALSE);
  64.             return NULL;
  65.         case SHARE_ADD:
  66.             data = INST_DATA(cl, obj);
  67.             add_shares(data);
  68.             return NULL;
  69.         case SHARE_ADDDIR:
  70.             data = INST_DATA(cl, obj);
  71.             add_directory(data);
  72.             return NULL;
  73.         case SHARE_REMOVE:
  74.             data = INST_DATA(cl, obj);
  75.             remove_shares(data, (long)(((muimsg)msg)->arg1));
  76.             return NULL;
  77.         case SHARE_SAVE:
  78.             data = INST_DATA(cl, obj);
  79.             save_shares(data);
  80.             return NULL;
  81.         case SHARE_SAVEAS:
  82.             data = INST_DATA(cl, obj);
  83.             save_shares_as(data);
  84.             return NULL;
  85.         case SHARE_LOAD:
  86.             data = INST_DATA(cl, obj);
  87.             load_shares(data, 0);
  88.             return NULL;
  89.         case SHARE_LOADAS:
  90.             data = INST_DATA(cl, obj);
  91.             load_shares_as(data, (int)(((muimsg)msg)->arg1));
  92.             return NULL;
  93.         case SHARE_UPLOAD:
  94.             data = INST_DATA(cl, obj);
  95.             upload_file_confirm(data, (char *)(((muimsg)msg)->arg1), (char *)(((muimsg)msg)->arg2));
  96.             return NULL;
  97.         case SHARE_NOTIFYALL:
  98.             data = INST_DATA(cl, obj);
  99.             notify_shares(data);
  100.             return NULL;
  101.         case SHARE_PLAY:
  102.             data = INST_DATA(cl, obj);
  103.             play_share(data);
  104.             return NULL;
  105.         case SHARE_ADDFILE:
  106.             data = INST_DATA(cl, obj);
  107.             add_file(data, (song)(((muimsg)msg)->arg1), (char *)(((muimsg)msg)->arg2));
  108.             return NULL;
  109.         case SHARE_ADDFILEN:
  110.             data = INST_DATA(cl, obj);
  111.             add_filename(data, (char *)(((muimsg)msg)->arg1));
  112.             return NULL;
  113.         case SHARE_SETDIR:
  114.             strcpy(FReqAddFiles->fr_Drawer, (char *)(((muimsg)msg)->arg1));
  115.             strcpy(FReqAddDir->fr_Drawer, (char *)(((muimsg)msg)->arg1));
  116.             return NULL;
  117.         case SHARE_UPDCOUNT:
  118.             data = INST_DATA(cl, obj);
  119.             update_count(data, (char *)(((muimsg)msg)->arg1));
  120.             return NULL;
  121.     }
  122.     return(DoSuperMethodA(cl, obj, msg));
  123. }
  124.  
  125.  
  126. MUI_LIST_DEST(sharelistdest, sharedata sd)
  127. {
  128.     char *path;
  129.  
  130.     numsongs--;
  131.     numbytes -= sd->size;
  132.     if (gui_onlinestate == ONLINE) {
  133.         path = MakeWinPath(sd->title);
  134.         nap_sendbuf(NAPC_REMOVESHARE, path);
  135.         free(path);
  136.     }
  137.     free(sd);
  138.  
  139.     return(0);
  140. }
  141.  
  142.  
  143. MUI_LIST_DISP(sharelistdisp, sharedata sd)
  144. {
  145.     static char size[16], md5[33], time[20], bitrate[16], freq[16], count[16];
  146.  
  147.     if (sd) {
  148.             *array++ = sd->title;
  149.             sprintf(size, "\33r%ld", sd->size);
  150.             *array++ = size;
  151.             sprintf(time, "\33r%ld:%02ld", sd->time/60, sd->time%60);
  152.             *array++ = time;
  153.             sprintf(bitrate, "\33r%ld", sd->bitrate);
  154.             *array++ = bitrate;
  155.             sprintf(freq, "\33l%ld", sd->freq);
  156.             *array++ = freq;
  157.             sprintf(count, "\33r%ld", sd->reqcount);
  158.             *array++ = count;
  159.             strcpy(md5, sd->md5);
  160.             *array = md5;
  161.     } else {
  162.         *array++ = (char *)MSG_LH_FILE;
  163.         *array++ = (char *)MSG_LH_SIZE;
  164.         *array++ = (char *)MSG_LH_TIME;
  165.         *array++ = (char *)MSG_LH_BITRATE;
  166.         *array++ = (char *)MSG_LH_FREQ;
  167.         *array++ = (char *)MSG_LH_COUNT;
  168.         *array   = (char *)MSG_LH_CHECKSUM;
  169.     }
  170.     return(0);
  171. }
  172.  
  173.  
  174. MUI_NLIST_COMP(sharelistcomp)
  175. {
  176.     sharedata entry1 = ncm->entry1;
  177.     sharedata entry2 = ncm->entry2;
  178.     LONG col1 = ncm->sort_type & MUIV_NList_TitleMark_ColMask;
  179.     LONG col2 = ncm->sort_type2 & MUIV_NList_TitleMark2_ColMask;
  180.     ULONG result = 0;
  181.  
  182.     if (ncm->sort_type == MUIV_NList_SortType_None) return (0);
  183.  
  184.     if (col1 == 0) {
  185.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  186.             result = (LONG) stricmp(entry2->title, entry1->title);
  187.         else
  188.             result = (LONG) stricmp(entry1->title, entry2->title);
  189.     }
  190.     else if (col1 == 1) {
  191.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  192.             result = entry2->size - entry1->size;
  193.         else
  194.             result = entry1->size - entry2->size;
  195.     }
  196.     else if (col1 == 2) {
  197.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  198.             result = entry2->time - entry1->time;
  199.         else
  200.             result = entry1->time - entry2->time;
  201.     }
  202.     else if (col1 == 3) {
  203.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  204.             result = entry2->bitrate - entry1->bitrate;
  205.         else
  206.             result = entry1->bitrate - entry2->bitrate;
  207.     }
  208.     else if (col1 == 4) {
  209.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  210.             result = entry2->freq - entry1->freq;
  211.         else
  212.             result = entry1->freq - entry2->freq;
  213.     }
  214.     else if (col1 == 5) {
  215.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  216.             result = entry2->reqcount - entry1->reqcount;
  217.         else
  218.             result = entry1->reqcount - entry2->reqcount;
  219.     }
  220.     else if (col1 == 6) {
  221.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  222.             result = (LONG) stricmp(entry2->md5, entry1->md5);
  223.         else
  224.             result = (LONG) stricmp(entry1->md5, entry2->md5);
  225.     }
  226.  
  227.     if ((result != 0) || (col1 == col2)) return (result);
  228.  
  229.     if (col2 == 0) {
  230.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  231.             result = (LONG) stricmp(entry2->title, entry1->title);
  232.         else
  233.             result = (LONG) stricmp(entry1->title, entry2->title);
  234.     }
  235.     else if (col2 == 1) {
  236.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  237.             result = entry2->size - entry1->size;
  238.         else
  239.             result = entry1->size - entry2->size;
  240.     }
  241.     else if (col2 == 2) {
  242.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  243.             result = entry2->time - entry1->time;
  244.         else
  245.             result = entry1->time - entry2->time;
  246.     }
  247.     else if (col2 == 3) {
  248.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  249.             result = entry2->bitrate - entry1->bitrate;
  250.         else
  251.             result = entry1->bitrate - entry2->bitrate;
  252.     }
  253.     else if (col2 == 4) {
  254.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  255.             result = entry2->freq - entry1->freq;
  256.         else
  257.             result = entry1->freq - entry2->freq;
  258.     }
  259.     else if (col2 == 5) {
  260.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  261.             result = entry2->reqcount - entry1->reqcount;
  262.         else
  263.             result = entry1->reqcount - entry2->reqcount;
  264.     }
  265.     else if (col2 == 6) {
  266.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  267.             result = (LONG) stricmp(entry2->md5, entry1->md5);
  268.         else
  269.             result = (LONG) stricmp(entry1->md5, entry2->md5);
  270.     }
  271.  
  272.     return (result);
  273. }
  274.  
  275.  
  276. MUI_APPMSG(ShareListAppMsgFunc)
  277. {
  278.     struct WBArg *ap;
  279.     struct AppMessage *amsg = *appmsg;
  280.     int i;
  281.     static char buf[256];
  282.  
  283.     for (ap=amsg->am_ArgList, i=0; i<amsg->am_NumArgs; i++, ap++)
  284.     {
  285.         NameFromLock(ap->wa_Lock, buf, sizeof(buf));
  286.         AddPart(buf, ap->wa_Name, sizeof(buf));
  287.         DoMethod(gui->shwin, SHARE_ADDFILEN, buf);
  288.     }
  289.  
  290.     return(0);
  291. }
  292.  
  293.  
  294. ULONG share_new(struct IClass *cl, Object *obj, struct opSet *msg)
  295. {
  296.     static const struct Hook sharelistdispHook    = { {NULL, NULL}, &sharelistdisp, NULL, NULL };
  297.     static const struct Hook sharelistcompHook    = { {NULL, NULL}, &sharelistcomp, NULL, NULL };
  298.     static const struct Hook sharelistdestHook    = { {NULL, NULL}, &sharelistdest, NULL, NULL };
  299.     static const struct Hook ShareListAppMsgHook  = { {NULL, NULL}, &ShareListAppMsgFunc, NULL, NULL };
  300.  
  301.     struct shdata *data;
  302.     Object *list, *stat, *BT_Add, *BT_AddDir, *BT_Remove, *BT_RemoveAll;
  303.  
  304.     if (obj = (Object *)DoSuperNew(cl, obj,
  305.         MUIA_HelpNode, "sharing",
  306.         MUIA_Window_ID, MAKE_ID('S','H','A','R'),
  307.         MUIA_Window_Title, MSG_SHARE_TITLE,
  308.         MUIA_Window_AppWindow, TRUE,
  309.         WindowContents, VGroup,
  310.             MUIA_HelpNode, "sharing",
  311.             Child, stat = TextObject,
  312.                 TextFrame,
  313.                 MUIA_Background, MUII_TextBack,
  314.                 MUIA_Text_PreParse, "\33c",
  315.             End,
  316.             Child, list = NListviewObject,
  317.                 MUIA_NListview_NList, NListObject,
  318.                     InputListFrame,
  319.                     MUIA_NList_Title, TRUE,
  320.                     MUIA_NList_Format, "BAR, BAR, BAR, BAR, BAR, BAR",
  321.                     MUIA_NList_DisplayHook, &sharelistdispHook,
  322.                     MUIA_NList_CompareHook2, &sharelistcompHook,
  323.                     MUIA_NList_DestructHook, &sharelistdestHook,
  324.                     MUIA_NList_MultiSelect, MUIV_NList_MultiSelect_Default,
  325.                     MUIA_NList_MinColSortable, 0,
  326.                     MUIA_CycleChain, 1,
  327.                 End,
  328.             End,
  329.             Child, HGroup,
  330.                 Child, BT_Add       = SimpleButton(MSG_SHARE_ADD_GAD         ),
  331.                 Child, BT_AddDir    = SimpleButton(MSG_SHARE_ADDRECURSIVE_GAD),
  332.                 Child, BT_Remove    = SimpleButton(MSG_SHARE_REMOVE_GAD      ),
  333.                 Child, BT_RemoveAll = SimpleButton(MSG_SHARE_REMOVEALL_GAD   ),
  334.             End,
  335.         End,
  336.         TAG_MORE, msg->ops_AttrList))
  337.     {
  338.         data = INST_DATA(cl,obj);
  339.         data->list = list;
  340.         data->stat = stat;
  341.  
  342.  
  343.         /* Default sort */
  344.  
  345.         DoMethod(list, MUIM_Set, MUIA_NList_TitleMark, 0);
  346.         DoMethod(list, MUIM_NList_Sort3, 0, MUIV_NList_SortTypeAdd_2Values, MUIV_NList_Sort3_SortType_Both);
  347.  
  348.         /* Window notify */
  349.  
  350.         DoMethod(obj, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, gui->iconpanel, 1, PANEL_CLOSESHARE);
  351.  
  352.         /* List notifies */
  353.  
  354.         DoMethod(list, MUIM_Notify, MUIA_NList_DoubleClick, MUIV_EveryTime, obj,  1, SHARE_PLAY);
  355.          DoMethod(list, MUIM_Notify, MUIA_NList_TitleClick,  MUIV_EveryTime, list, 4, MUIM_NList_Sort3, MUIV_TriggerValue, MUIV_NList_SortTypeAdd_2Values, MUIV_NList_Sort3_SortType_Both);
  356.         DoMethod(list, MUIM_Notify, MUIA_NList_TitleClick2, MUIV_EveryTime, list, 4, MUIM_NList_Sort3, MUIV_TriggerValue, MUIV_NList_SortTypeAdd_2Values, MUIV_NList_Sort3_SortType_2);
  357.         DoMethod(list, MUIM_Notify, MUIA_NList_SortType,    MUIV_EveryTime, list, 3, MUIM_Set, MUIA_NList_TitleMark,  MUIV_TriggerValue);
  358.         DoMethod(list, MUIM_Notify, MUIA_NList_SortType2,   MUIV_EveryTime, list, 3, MUIM_Set, MUIA_NList_TitleMark2, MUIV_TriggerValue);
  359.         DoMethod(list, MUIM_Notify, MUIA_AppMessage,        MUIV_EveryTime, list, 3, MUIM_CallHook, &ShareListAppMsgHook, MUIV_TriggerValue);
  360.  
  361.         /* Button notifies */
  362.  
  363.         DoMethod(BT_Add,       MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, SHARE_ADD      );
  364.         DoMethod(BT_AddDir,    MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, SHARE_ADDDIR   );
  365.         DoMethod(BT_Remove,    MUIM_Notify, MUIA_Pressed, FALSE, obj, 2, SHARE_REMOVE, 0);
  366.         DoMethod(BT_RemoveAll, MUIM_Notify, MUIA_Pressed, FALSE, obj, 2, SHARE_REMOVE, 1);
  367.  
  368.         /* Allocate file requesters */
  369.  
  370.         FReqAddFiles = AllocAslRequestTags(ASL_FileRequest,
  371.             ASLFR_TitleText, MSG_SHARE_ADD_REQ,
  372.             ASLFR_InitialPattern, (ULONG)"#?.(mp(2|3)|wma)",
  373.             ASLFR_InitialDrawer, (ULONG)prf->dlpath,
  374.             ASLFR_DoPatterns, TRUE,
  375.             ASLFR_DoMultiSelect, TRUE,
  376.             ASLFR_RejectIcons, TRUE,
  377.             TAG_DONE);
  378.         FReqAddDir = AllocAslRequestTags(ASL_FileRequest,
  379.             ASLFR_TitleText, MSG_SHARE_ADDDIR_REQ,
  380.             ASLFR_InitialDrawer, (ULONG)prf->dlpath,
  381.             ASLFR_DrawersOnly, TRUE,
  382.             TAG_DONE);
  383.         FReqLibrary = AllocAslRequestTags(ASL_FileRequest,
  384.             ASLFR_InitialFile, "Amster.shares",
  385.             ASLFR_InitialDrawer, "PROGDIR:",
  386.             ASLFR_RejectIcons, TRUE,
  387.             TAG_DONE);
  388.  
  389.         return((ULONG)obj);
  390.     }
  391.     return(0);
  392. }
  393.  
  394.  
  395. /* Private functions */
  396.  
  397.  
  398. void add_filename(struct shdata *data, char *fname)
  399. {
  400.     sharedata sd;
  401.     struct FileInfoBlock *fib;
  402.     BPTR lock;
  403.  
  404.     if (!(fib = AllocDosObject(DOS_FIB, NULL))) return;
  405.  
  406.     if (sd = malloc(sizeof(_sharedata))) {
  407.         memset(sd, 0, sizeof(_sharedata));
  408.  
  409.         strcpy(sd->title, fname);
  410.         if (lock = Lock(fname, ACCESS_READ)) {
  411.             if (Examine(lock, fib)) {
  412.                 sd->size = fib->fib_Size;
  413.                 if (NameFromLock(lock, sd->title, 255)) {
  414.                     if (fib->fib_DirEntryType < 0) add_shareinfo(data, sd, lock);
  415.                     else if (fib->fib_DirEntryType > 0) {
  416.                         add_recursive(data, sd, lock, sd->title);
  417.                         UnLock(lock);
  418.                     }
  419.                 }
  420.                 else UnLock(lock);
  421.             }
  422.         }
  423.     }
  424.  
  425.     FreeDosObject(DOS_FIB, fib);
  426. }
  427.  
  428.  
  429. void add_file(struct shdata *data, song sdl, char *fname)
  430. {
  431.     sharedata sd;
  432.     struct FileInfoBlock *fib;
  433.     BPTR lock;
  434.  
  435.     if (sd = malloc(sizeof(_sharedata))) {
  436.         memset(sd, 0, sizeof(_sharedata));
  437.  
  438.         if (fib = AllocDosObject(DOS_FIB, NULL)) {
  439.             if (lock = Lock(fname, ACCESS_READ)) {
  440.                 NameFromLock(lock, sd->title, 255);
  441.                 UnLock(lock);
  442.             }
  443.             FreeDosObject(DOS_FIB, fib);
  444.         }
  445.  
  446.         if (!sd->title) strcpy(sd->title, fname);
  447.         strncpy(sd->md5, sdl->md5, 32);
  448.         sd->size    = sdl->size;
  449.         sd->bitrate = sdl->bit;
  450.         sd->freq    = sdl->freq;
  451.         sd->time    = sdl->time;
  452.  
  453.         DoMethod(data->list, MUIM_NList_InsertSingle, sd, MUIV_NList_Insert_Sorted);
  454.         numsongs++; numbytes += sd->size;
  455.         sharechanged = TRUE;
  456.         update_stat(data);
  457.         if (gui_onlinestate == ONLINE) nap_notifyshare(sd);
  458.     }
  459.  
  460.     return;
  461. }
  462.  
  463.  
  464. void add_shares(struct shdata *data)
  465. {
  466.     sharedata sd;
  467.     BPTR lock;
  468.     struct FileInfoBlock *fib;
  469.     int i;
  470.     u_long win;
  471.  
  472.     get(gui->shwin, MUIA_Window_Window, &win);
  473.  
  474.     if (FReqAddFiles) {
  475.         if (AslRequestTags(FReqAddFiles, ASLFR_Window, win, TAG_DONE)) {
  476.                 if (fib = AllocDosObject(DOS_FIB, NULL)) {
  477.                     for (i=0; i<FReqAddFiles->fr_NumArgs; i++) {
  478.                         if (sd = malloc(sizeof(_sharedata))) {
  479.                             memset(sd, 0, sizeof(_sharedata));
  480.                             strcpy(sd->title, FReqAddFiles->fr_Drawer);
  481.                             AddPart(sd->title, FReqAddFiles->fr_ArgList[i].wa_Name, 255);
  482.                             if (lock = Lock(sd->title, ACCESS_READ)) {
  483.                                 if (Examine(lock, fib)) {
  484.                                     sd->size = fib->fib_Size;
  485.                                     if (NameFromLock(lock, sd->title, 255)) {
  486.                                         if (fib->fib_DirEntryType < 0) add_shareinfo(data, sd, lock);
  487.                                         else if (fib->fib_DirEntryType > 0) {
  488.                                             add_recursive(data, sd, lock, sd->title);
  489.                                             UnLock(lock);
  490.                                         }
  491.                                     }
  492.                                     else UnLock(lock);
  493.                                 }
  494.                             }
  495.                         }
  496.                     }
  497.                     FreeDosObject(DOS_FIB, fib);
  498.                 }
  499.         }
  500.         if (sharefailed) {
  501.             MUI_Request(gui->app, gui->shwin, 0L,
  502.                 (char *)MSG_ERROR_TITLE,
  503.                 (char *)MSG_OK_GAD,
  504.                 (char *)MSG_SHARE_ADDFAILED);
  505.             sharefailed = FALSE;
  506.         }
  507.     }
  508. }
  509.  
  510.  
  511. void add_directory(struct shdata *data)
  512. {
  513.     sharedata sd;
  514.     BPTR lock;
  515.     struct FileInfoBlock *fib;
  516.     u_long win;
  517.  
  518.     get(gui->shwin, MUIA_Window_Window, &win);
  519.  
  520.     if (FReqAddDir) {
  521.         if (AslRequestTags(FReqAddDir, ASLFR_Window, win, TAG_DONE)) {
  522.                 if (fib = AllocDosObject(DOS_FIB, NULL)) {
  523.                     if (sd = malloc(sizeof(_sharedata))) {
  524.                         memset(sd, 0, sizeof(_sharedata));
  525.                         strcpy(sd->title, FReqAddDir->fr_Drawer);
  526.                         if (lock = Lock(sd->title, ACCESS_READ)) {
  527.                             if (Examine(lock, fib)) {
  528.                                 sd->size = fib->fib_Size;
  529.                                 if (NameFromLock(lock, sd->title, 255)) {
  530.                                     if (fib->fib_DirEntryType > 0) {
  531.                                         add_recursive(data, sd, lock, sd->title);
  532.                                         UnLock(lock);
  533.                                     }
  534.                                 }
  535.                                 else UnLock(lock);
  536.                             }
  537.                         }
  538.                     }
  539.                     FreeDosObject(DOS_FIB, fib);
  540.                 }
  541.         }
  542.         if (sharefailed) {
  543.             MUI_Request(gui->app, gui->shwin, 0L,
  544.                 (char *)MSG_ERROR_TITLE,
  545.                 (char *)MSG_OK_GAD,
  546.                 (char *)MSG_SHARE_ADDFAILED);
  547.             sharefailed = FALSE;
  548.         }
  549.     }
  550. }
  551.  
  552.  
  553. void add_recursive(struct shdata *data, sharedata sd, BPTR dirlock, const char *dirname)
  554. {
  555.     ULONG namelen;
  556.     long len;
  557.     struct ExAllControl *eac;
  558.     struct ExAllData *ead;
  559.     APTR eadata;
  560.     BOOL more;
  561.     char *name;
  562.     BPTR lock;
  563.     struct FileInfoBlock *fib;
  564.     const long buffersize = 4096;
  565.  
  566.     if (dirlock) {
  567.         namelen = strlen(dirname);
  568.         eac = AllocDosObject(DOS_EXALLCONTROL, NULL);
  569.         if (eac) {
  570.             eac->eac_LastKey = 0;
  571.             eac->eac_MatchString = 0;
  572.             eac->eac_MatchFunc = 0;
  573.             eadata = malloc(buffersize);
  574.             if (eadata) {
  575.                 do {
  576.                     more = ExAll(dirlock, eadata, buffersize, ED_TYPE, eac);
  577.                     if (eac->eac_Entries > 0) {
  578.                         ead = eadata;
  579.                         do {
  580.                             len = namelen + strlen(ead->ed_Name);
  581.                             name = (char *)malloc(len+5);
  582.                             if (name) {
  583.                                 strcpy(name, dirname);
  584.                                 if (AddPart(name, ead->ed_Name, len+5)) {
  585.                                     if (ead->ed_Type > 0) {
  586.                                         lock = Lock(name, ACCESS_READ);
  587.                                         if (lock) {
  588.                                             add_recursive(data, sd, lock, name);
  589.                                             UnLock(lock);
  590.                                         }
  591.                                     }
  592.                                     else if (ead->ed_Type < 0) {
  593.                                         if (sd = malloc(sizeof(_sharedata))) {
  594.                                             memset(sd, 0, sizeof(_sharedata));
  595.                                             strcpy(sd->title, name);
  596.                                             if (fib = AllocDosObject(DOS_FIB, NULL)) {
  597.                                                 lock = Lock(name, ACCESS_READ);
  598.                                                 if (lock) {
  599.                                                     if (Examine(lock, fib)) {
  600.                                                         sd->size = fib->fib_Size;
  601.                                                         add_shareinfo(data, sd, lock);
  602.                                                     }
  603.                                                 }
  604.                                                 FreeDosObject(DOS_FIB, fib);
  605.                                             }
  606.                                         }
  607.                                     }
  608.                                 }
  609.                                 free(name);
  610.                             }
  611.                             ead = ead->ed_Next;
  612.                         } while(ead);
  613.                     }
  614.                     if ((!more) && (IoErr() != ERROR_NO_MORE_ENTRIES)) break;
  615.                     if (eac->eac_Entries == 0) continue;
  616.                 } while (more);
  617.                 free(eadata);
  618.             }
  619.             FreeDosObject(DOS_EXALLCONTROL, eac);
  620.         }
  621.     }
  622. }
  623.  
  624.  
  625. void add_shareinfo(struct shdata *data, sharedata sd, BPTR lock)
  626. {
  627.     unsigned int m_id, m_layer, m_bit, m_freq, m_mode;
  628.     APTR buffer;
  629.     BPTR fh;
  630.     int i=0, j=0, len, total, col;
  631.     long vbrbytes = 0, vbrframes = 0, vbr = 0;
  632.     BOOL header = FALSE;
  633.     int badhdr[10];
  634.     char *suffix;
  635.  
  636.     sharedata sdtmp;
  637.     ULONG tmp;
  638.  
  639.     md5_state_t state;
  640.     md5_byte_t digest[16];
  641.     int di;
  642.  
  643.     /*    MP3 information source:
  644.         http://mp3tech.free.fr/programmers/frame_header.html
  645.     */
  646.  
  647.     int mp3_bitrates[14][6] = {
  648.     /*   V1L1,V1L2,V1L3,V2L1,V2L2,V2L3   */
  649.         {  32,  32,  32,  32,   8,   8 },
  650.         {  64,  48,  40,  48,  16,  16 },
  651.         {  96,  56,  48,  56,  24,  24 },
  652.         { 128,  64,  56,  64,  32,  32 },
  653.         { 160,  80,  64,  80,  40,  40 },
  654.         { 192,  96,  80,  96,  48,  48 },
  655.         { 224, 112,  96, 112,  56,  56 },
  656.         { 256, 128, 112, 128,  64,  64 },
  657.         { 288, 160, 128, 144,  80,  80 },
  658.         { 320, 192, 160, 160,  96,  96 },
  659.         { 352, 224, 192, 176, 112, 112 },
  660.         { 384, 256, 224, 192, 128, 128 },
  661.         { 416, 320, 256, 224, 144, 144 },
  662.         { 448, 384, 320, 256, 160, 160 }
  663.     };
  664. /*    V1 = MPEG Version 1
  665.     V2 = MPEG Version 2 and Version 2.5
  666.     L1 = Layer I
  667.     L2 = Layer II
  668.     L3 = Layer III
  669. */
  670.  
  671.     int mp3_frequencies[3][3] = {
  672.     /*    MPEG1, MPEG2, MPEG2.5    */
  673.         { 44100, 22050, 11025 },
  674.         { 48000, 24000, 12000 },
  675.         { 32000, 16000,  8000 }
  676.     };
  677.  
  678.     if (IsIn(sd->title, '"') || IsIn(sd->title, '\\')) {
  679.         gui_debugf((char *)MSG_SHARE_ILLEGALCHARS, sd->title);
  680.         sharefailed = TRUE;
  681.         UnLock(lock);
  682.         return;
  683.     }
  684.  
  685.     suffix = sd->title + strlen(sd->title) - 4;
  686.     if (stricmp(suffix, ".mp3") != 0 && stricmp(suffix, ".mp2") != 0 && stricmp(suffix, ".wma") != 0) {
  687.         gui_debugf((char *)MSG_SHARE_INVALIDEXTENSION, sd->title);
  688.         sharefailed = TRUE;
  689.         UnLock(lock);
  690.         return;
  691.     }
  692.  
  693.     GetAttr(MUIA_NList_Entries, data->list, &tmp);
  694.     total = tmp;
  695.  
  696.     while (i < total) {
  697.         DoMethod(data->list, MUIM_NList_GetEntry, i, &sdtmp);
  698.         if (sdtmp) if (strcmp(sd->title, sdtmp->title) == 0) {
  699.             gui_debugf((char *)MSG_SHARE_EXISTS, sd->title);
  700.             sharefailed = TRUE;
  701.             UnLock(lock);
  702.             return;
  703.         }
  704.         i++;
  705.     }
  706.  
  707.     if (fh = OpenFromLock(lock)) {
  708.         if (buffer = AllocMem(300032, MEMF_ANY)) {
  709.  
  710.             md5_init(&state);
  711.  
  712.             len = Read(fh, buffer, 300032);
  713.             if (len > 0) {
  714.  
  715.                 md5_append(&state, (const md5_byte_t *)buffer, len);
  716.                 md5_finish(&state, digest);
  717.                 for (di = 0; di < 16; ++di)
  718.                     sprintf(sd->md5+di*2, "%02x", digest[di]);
  719.  
  720.                 /* Only check first 128 kB for valid MP3 header */
  721.                 if (len > 128*1024) len = 128*1024;
  722.  
  723.                 /* Check for VBR */
  724.                 for (i=0; i<len; i++) {
  725.                     if (*((unsigned char *)buffer+i) == 'X')
  726.                         if (*((unsigned char *)buffer+i+1) == 'i')
  727.                             if (*((unsigned char *)buffer+i+2) == 'n')
  728.                                 if (*((unsigned char *)buffer+i+3) == 'g') {
  729.                                     j = i + 7;
  730.                                     if ((*((char *)buffer+j) & 1) && ((*((char *)buffer+j) & 2) >> 1)) {
  731.                                         j++;
  732.                                         vbrframes = *((unsigned long *)buffer+j/4);
  733.                                         vbrbytes = *((unsigned long *)buffer+(j+4)/4);
  734.                                         j += 7;
  735.                                     }
  736.                                     if (vbrframes > 0 && vbrbytes > 0) vbr = ((vbrbytes / vbrframes) * 1000) / 3265;
  737.                                     break;
  738.                                 }
  739.                 }
  740.  
  741.                 i = j;
  742.                 if (stcd_i(buffer, badhdr) == 8 && i < 417) i = 417;
  743.                 /* Work-around for "MpegDJ Encoder" bug */
  744.  
  745.                 while (!header && i<len-3) {
  746.                     /* Seek until synchronization is found (%11111111.111xxxxx) */
  747.                     if (*((unsigned char *)buffer+i) == 255) {
  748.                         if (*((unsigned char *)buffer+i+1) >= 224) {
  749.  
  750.                             /*    MPEG Audio version ID
  751.                                 00 - MPEG Version 2.5 (later extension of MPEG 2)
  752.                                 01 - reserved
  753.                                 10 - MPEG Version 2 (ISO/IEC 13818-3)
  754.                                 11 - MPEG Version 1 (ISO/IEC 11172-3)
  755.                             */
  756.  
  757.                             m_id = 3 - ((*((char *)buffer+i+1) & 24)>>3);
  758.                             if (m_id == 3) m_id = 1;
  759.  
  760.                             /*    Layer description
  761.                                 00 - reserved
  762.                                 01 - Layer III
  763.                                 10 - Layer II
  764.                                 11 - Layer I
  765.                             */
  766.  
  767.                             m_layer = 4 - ((*((char *)buffer+i+1) & (2+4))>>1);
  768.                             m_bit   =      (*((char *)buffer+i+2) & (16+32+64+128))>>4;
  769.                             m_freq  =      (*((char *)buffer+i+2) & (4+8))>>2;
  770.  
  771.                             /*    Channel Mode
  772.                                 00 - Stereo
  773.                                 01 - Joint stereo (Stereo)
  774.                                 10 - Dual channel (2 mono channels)
  775.                                 11 - Single channel (Mono)
  776.                             */
  777.  
  778.                             m_mode  =      (*((char *)buffer+i+3) & (64+128))>>6;
  779.  
  780.                             col = m_layer-1;
  781.                             if (m_id == 1) col=col+3;
  782.  
  783.                             if (m_bit>0 && m_bit<15 && m_freq < 3 && m_layer < 4 && m_id != 2) {
  784.  
  785.                                 header = TRUE;
  786.  
  787.                                 sd->freq = mp3_frequencies[m_freq][m_id];
  788.                                 if (vbr > 0) sd->bitrate = vbr;
  789.                                 else sd->bitrate = mp3_bitrates[m_bit-1][col];
  790.  
  791.                                 if (m_layer == 2) { /* Sanity checks */
  792.                                     if ((sd->bitrate == 32 || sd->bitrate == 48 || sd->bitrate == 46 || sd->bitrate == 80) && m_mode != 3) header = FALSE;
  793.                                     if ((sd->bitrate == 224 || sd->bitrate == 256 || sd->bitrate == 320 || sd->bitrate == 384) && m_mode == 3) header = FALSE;
  794.                                 }
  795.  
  796.                                 sd->time = (sd->size-i)/(sd->bitrate*125);
  797.                                 /* 'i' is the length of ID3v2 tag. ID3v1 size is always 128 bytes,
  798.                                    so it's not worth the overhead to check for this.
  799.                                    128 bytes of a 128 kbps MP3 = 0.000008 seconds! */
  800.                             }
  801.                         }
  802.                     }
  803.                     i++;
  804.                 }
  805.             }
  806.             FreeMem(buffer, 300032);
  807.         }
  808.         Close(fh);
  809.         if (header) {
  810.             DoMethod(data->list, MUIM_NList_InsertSingle, sd, MUIV_NList_Insert_Sorted);
  811.             numsongs++; numbytes += sd->size;
  812.             sharechanged = TRUE;
  813.             update_stat(data);
  814.             if (gui_onlinestate == ONLINE) nap_notifyshare(sd);
  815.         }
  816.         else {
  817.             gui_debugf((char *)MSG_SHARE_ADDERROR, sd->title, sd->size, sd->bitrate, sd->freq);
  818.             sharefailed = TRUE;
  819.         }
  820.     }
  821.     else UnLock(lock);
  822.  
  823. }
  824.  
  825.  
  826. void notify_shares(struct shdata *data)
  827. {
  828.     sharedata sd;
  829.     u_long tmp;
  830.     int i, total;
  831.  
  832.     if (gui_onlinestate < LOGGING_IN) return;
  833.  
  834.     GetAttr(MUIA_NList_Entries, data->list, &tmp);
  835.     total = tmp;
  836.  
  837.     if (total > 0) {
  838.         gui_stat((char *)MSG_STATUS2_NOTIFYALL);
  839.         for (i=0; i<total; i++) {
  840.             DoMethod(data->list, MUIM_NList_GetEntry, i, &sd);
  841.             if (!sd) break;
  842.             nap_notifyshare(sd);
  843.         }
  844.     }
  845. }
  846.  
  847.  
  848. void remove_shares(struct shdata *data, long t)
  849. {
  850.     sharedata sd;
  851.     u_long tmp;
  852.     int total;
  853.  
  854.     GetAttr(MUIA_NList_Entries, data->list, &tmp);
  855.     total = tmp;
  856.  
  857.     if (total == 0) return;
  858.  
  859.     switch(t) {
  860.         case 0: /* Remove marked */
  861.             set(data->list, MUIA_NList_Quiet, MUIV_NList_Quiet_Visual);
  862.             DoMethod(data->list, MUIM_NList_Remove, MUIV_NList_Remove_Selected);
  863.             update_stat(data);
  864.             set(data->list,MUIA_NList_Quiet, MUIV_NList_Quiet_None);
  865.             break;
  866.         case 1: /* Remove all */
  867.             set(data->list, MUIA_NList_Quiet, MUIV_NList_Quiet_Visual);
  868.             for (;;) {
  869.                 DoMethod(data->list, MUIM_NList_GetEntry, 0, &sd);
  870.                 if (!sd) break;
  871.                 DoMethod(data->list, MUIM_NList_Remove, MUIV_NList_Remove_First);
  872.             }
  873.             update_stat(data);
  874.             set(data->list, MUIA_NList_Quiet, MUIV_NList_Quiet_None);
  875.             break;
  876.     }
  877.     sharechanged = TRUE;
  878. }
  879.  
  880.  
  881. void save_shares(struct shdata *data)
  882. {
  883.     sharedata sd;
  884.     int i;
  885.     BPTR fh;
  886.     char buf[512], *tmp;
  887.  
  888.     strcpy(buf, FReqLibrary->fr_Drawer);
  889.     AddPart(buf, FReqLibrary->fr_File, 511);
  890.  
  891.     fh = Open(buf, MODE_NEWFILE);
  892.     if (!fh) return;
  893.  
  894.     for (i=0; ; i++) {
  895.         DoMethod(data->list, MUIM_NList_GetEntry, i, &sd);
  896.         if (!sd) break;
  897.         if (tmp = strrep(sd->title, "\"", "*\"")) {
  898.             sprintf(buf, "\"%s\" %s %ld %ld %ld %ld REQCOUNT %ld\n", tmp, sd->md5, sd->size, sd->bitrate, sd->freq, sd->time, sd->reqcount);
  899.             free(tmp);
  900.             Write(fh, buf, strlen(buf)); /* Should be buffered, check FWrite */
  901.         }
  902.     }
  903.  
  904.     Close(fh);
  905.     sharechanged = FALSE;
  906. }
  907.  
  908.  
  909. void save_shares_as(struct shdata *data)
  910. {
  911.     u_long win;
  912.  
  913.     get(gui->win, MUIA_Window_Window, &win);
  914.     if (FReqLibrary) {
  915.         if (AslRequestTags(FReqLibrary,
  916.             ASLFR_Window, win,
  917.             ASLFR_TitleText, MSG_SHARE_SAVEAS,
  918.             ASLFR_DoSaveMode, TRUE,
  919.             TAG_DONE)) {
  920.                     save_shares(data);
  921.         }
  922.     }
  923. }
  924.  
  925.  
  926. void load_shares(struct shdata *data, int merge)
  927. {
  928.     sharedata sd;
  929.     int line = 0;
  930.     BPTR fh;
  931.     char buf[512], sharefile[512];
  932.     LONG argarray[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
  933.     UBYTE *argstr = "PATH/A,MD5/A,SIZE/A/N,BITRATE/A/N,FREQUENCY/A/N,TIME/A/N,REQCOUNT/K/N";
  934.     struct RDArgs *rdargs;
  935.  
  936.     if (merge == 0) remove_shares(data, 1);
  937.  
  938.     strcpy(sharefile, FReqLibrary->fr_Drawer);
  939.     AddPart(sharefile, FReqLibrary->fr_File, 511);
  940.  
  941.     if (fh = Open(sharefile, MODE_OLDFILE)) {
  942.         set(data->list, MUIA_NList_Quiet, MUIV_NList_Quiet_Full);
  943.         if (rdargs = AllocDosObject(DOS_RDARGS, NULL)) {
  944.             while (FGets(fh, buf, 512)) {
  945.                 line++;
  946.  
  947.                 rdargs->RDA_Buffer = NULL;
  948.                 rdargs->RDA_Source.CS_Buffer = buf;
  949.                 rdargs->RDA_Source.CS_Length = strlen(buf);
  950.                 rdargs->RDA_Source.CS_CurChr = 0;
  951.  
  952.                 if (ReadArgs(argstr, argarray, rdargs)) {
  953.                     if (sd = malloc(sizeof(_sharedata))) {
  954.                         strcpy(sd->title,  (char *)argarray[ ARG_PATH     ]);
  955.                         strcpy(sd->md5,    (char *)argarray[ ARG_MD5      ]);
  956.                         sd->size     =   *((long *)argarray[ ARG_SIZE     ]);
  957.                         sd->bitrate  =   *((long *)argarray[ ARG_BITRATE  ]);
  958.                         sd->freq     =   *((long *)argarray[ ARG_FREQ     ]);
  959.                         sd->time     =   *((long *)argarray[ ARG_TIME     ]);
  960.                         if (argarray[ARG_REQCOUNT]) sd->reqcount = *((long *)argarray[ ARG_REQCOUNT ]);
  961.                         else sd->reqcount = 0;
  962.  
  963.                         DoMethod(data->list, MUIM_NList_InsertSingle, sd, MUIV_NList_Insert_Bottom);
  964.                         numsongs++; numbytes += sd->size;
  965.                         if (gui_onlinestate == ONLINE) nap_notifyshare(sd);
  966.                     }
  967.                     FreeArgs(rdargs);
  968.                 }
  969.                 else gui_debugf((char *)MSG_PARSE_ERROR, sharefile, line);
  970.             }
  971.             FreeDosObject(DOS_RDARGS, rdargs);
  972.         }
  973.  
  974.         set(data->list, MUIA_NList_Quiet, MUIV_NList_Quiet_None);
  975.         update_stat(data);
  976.  
  977.         Close(fh);
  978.     }
  979.     sharechanged = FALSE;
  980. }
  981.  
  982.  
  983. void load_shares_as(struct shdata *data, int merge)
  984. {
  985.     u_long win;
  986.  
  987.     get(gui->win, MUIA_Window_Window, &win);
  988.     if (FReqLibrary) {
  989.         if (AslRequestTags(FReqLibrary,
  990.             ASLFR_Window, win,
  991.             ASLFR_TitleText, MSG_SHARE_LOADAS,
  992.             TAG_DONE)) {
  993.                     load_shares(data, merge);
  994.         }
  995.     }
  996. }
  997.  
  998.  
  999. void update_stat(struct shdata *data)
  1000. {
  1001.     static char buf[100], totalsize[8];
  1002.     char descriptor[16];
  1003.     unsigned long number, tempnumber;
  1004.  
  1005.     if (numbytes >= (1024*1024*1024)) {
  1006.         strcpy(descriptor, MSG_SHARE_STAT_GB);
  1007.         tempnumber = numbytes/1024/1024*10/1024;
  1008.         number = tempnumber/10;
  1009.         tempnumber = tempnumber-(number*10);
  1010.         sprintf(totalsize,"%d.%d", number, tempnumber);
  1011.     }
  1012.     else if (numbytes >= (1024*1024)) {
  1013.         strcpy(descriptor, MSG_SHARE_STAT_MB);
  1014.         tempnumber = numbytes/1024*10/1024;
  1015.         number = tempnumber/10;
  1016.         tempnumber = tempnumber-(number*10);
  1017.         sprintf(totalsize, "%d.%d", number, tempnumber);
  1018.     }
  1019.     else {
  1020.         strcpy(descriptor, MSG_SHARE_STAT_KB);
  1021.         number = numbytes/1024;
  1022.         sprintf(totalsize, "%d", number);
  1023.     }
  1024.  
  1025.     sprintf(buf, MSG_SHARE_STAT_TMP, numsongs, totalsize, descriptor);
  1026.     set(data->stat, MUIA_Text_Contents, buf);
  1027. }
  1028.  
  1029.  
  1030. void play_share(struct shdata *data)
  1031. {
  1032.     sharedata sd;
  1033.     char buf[1024], *command;
  1034.  
  1035.     DoMethod(data->list, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &sd);
  1036.     if (sd) {
  1037.         if (prf->scripts[PRFE_LIB_DCLICK]) {
  1038.             sprintf(buf, "Run <>NIL: %s", prf->scripts[PRFE_LIB_DCLICK]);
  1039.             if (command = strrep(buf, "%f", sd->title)) {
  1040.                 Execute(command, 0, 0);
  1041.                 free(command);
  1042.             }
  1043.         }
  1044.     }
  1045. }
  1046.  
  1047.  
  1048. void upload_file_confirm(struct shdata *data, char *user, char *fname)
  1049. /* Called from napster.c */
  1050. {
  1051.     sharedata sd;
  1052.     song s;
  1053.     int i=0, total;
  1054.     ULONG tmp;
  1055.     BOOL found = FALSE;
  1056.     char *path;
  1057.  
  1058.     GetAttr(MUIA_NList_Entries, data->list, &tmp);
  1059.     total = tmp;
  1060.  
  1061.     gui_debugf((char *)MSG_SHARE_REQFILE, user, fname);
  1062.  
  1063.     while (i<total && !found) {
  1064.         DoMethod(data->list, MUIM_NList_GetEntry, i, &sd);
  1065.         if (sd) {
  1066.             path = MakeWinPath(sd->title);
  1067.             if (strcmp(path, fname) == 0) found = TRUE;
  1068.             free(path);
  1069.         }
  1070.         i++;
  1071.     }
  1072.  
  1073.     if (!found) {
  1074.         gui_debug((char *)MSG_SHARE_NOTFOUND);
  1075.         return;
  1076.     }
  1077.  
  1078.     s = malloc(sizeof(_song));
  1079.     if (!s) return;
  1080.     memset(s, 0, sizeof(_song));
  1081.  
  1082.     s->title = strdup(sd->title);
  1083.     s->md5 = strdup(sd->md5);
  1084.     s->size = sd->size;
  1085.     s->bit = sd->bitrate;
  1086.     s->freq = sd->freq;
  1087.     s->time = sd->time;
  1088.     s->user = strdup(user);
  1089.     /* At this point we don't know IP and link speed - can't complete the struct */
  1090.  
  1091.     ul_addq(s);
  1092. }
  1093.  
  1094.  
  1095. void update_count(struct shdata *data, char *fname)
  1096. {
  1097.     sharedata sd;
  1098.     int i;
  1099.     long pos;
  1100.  
  1101.     for (i=0; ; i++) {
  1102.         DoMethod(data->list, MUIM_NList_GetEntry, i, &sd);
  1103.         if (!sd) return;
  1104.         if (strcmp(sd->title, fname) == 0) break;
  1105.     }
  1106.  
  1107.     /* Update statistics (count) */
  1108.     sd->reqcount++;
  1109.     sharechanged = TRUE;
  1110.  
  1111.     pos = MUIV_NList_GetPos_Start;
  1112.     DoMethod(data->list, MUIM_NList_GetPos, sd, &pos);
  1113.     DoMethod(data->list, MUIM_NList_Redraw, pos);
  1114. }
  1115.  
  1116.  
  1117. void nap_notifyshare(sharedata sd)
  1118. {
  1119.     char *path, *suffix;
  1120.  
  1121.     /* In case invalid files were added manually or with an earlier version */
  1122.     if (IsIn(sd->title, '"') || IsIn(sd->title, '\\')) {
  1123.         gui_debugf((char *)MSG_SHARE_ILLEGALCHARS, sd->title);
  1124.         return;
  1125.     }
  1126.  
  1127.     suffix = sd->title + strlen(sd->title) - 4;
  1128.     if (stricmp(suffix, ".mp3") != 0 && stricmp(suffix, ".mp2") != 0 && stricmp(suffix, ".wma") != 0) {
  1129.         gui_debugf((char *)MSG_SHARE_INVALIDEXTENSION, sd->title);
  1130.         return;
  1131.     }
  1132.  
  1133.     path = MakeWinPath(sd->title);
  1134.     sprintf(nap_buf, "\"%s\" %s-%ld %ld %ld %ld %ld", path, sd->md5, sd->size, sd->size, sd->bitrate, sd->freq, sd->time);
  1135.     free(path);
  1136.     nap_send(NAPC_NOTIFYSHARE);
  1137. }
  1138.  
  1139.  
  1140. char *strrep(char *str1, char *old_str, char *new_str)
  1141. {
  1142.     char *str;
  1143.     int len, i;
  1144.  
  1145.     /* Allocate memory for the new string (worst-case) */
  1146.     if (!(str = malloc(strlen(str1)*(strlen(new_str)/strlen(old_str)+1)))) return NULL;
  1147.     str[0] = '\0';
  1148.  
  1149.     for (i=0; i<strlen(str1); i++) {
  1150.         if (strncmp(str1+i, old_str, strlen(old_str)) == 0) {
  1151.             strcat(str, new_str);
  1152.             i += strlen(old_str)-1;
  1153.         }
  1154.         else {
  1155.             len = strlen(str);
  1156.             str[len] = str1[i];
  1157.             str[len+1] = '\0';
  1158.         }
  1159.     }
  1160.  
  1161.     return str;
  1162. }
  1163.  
  1164.  
  1165. char *MakeWinPath(char *AmigaPath)
  1166. /* PRE: The AmigaPath must contain max. 1 colon */
  1167. {
  1168.     char *WinPath;
  1169.     int i, j;
  1170.  
  1171.     if (!(WinPath = malloc(strlen(AmigaPath)+2))) return AmigaPath;
  1172.  
  1173.     for (i=0, j=0; i<strlen(AmigaPath); i++, j++) {
  1174.         if (AmigaPath[i] == '/') WinPath[j] = '\\';
  1175.         else if (AmigaPath[i] == ':') {
  1176.             WinPath[j++] = ':';
  1177.             WinPath[j] = '\\';
  1178.         }
  1179.         else WinPath[j] = AmigaPath[i];
  1180.     }
  1181.     WinPath[j] = '\0';
  1182.  
  1183.     return WinPath;
  1184. }
  1185.  
  1186.  
  1187. BOOL IsIn(char *string, char c)
  1188. {
  1189.     int i;
  1190.  
  1191.     for (i=0; i<strlen(string); i++)
  1192.         if (string[i] == c) return TRUE;
  1193.  
  1194.     return FALSE;
  1195. }
  1196.